/*
 * @Author: HZK
 * @Date: 2020-10-19 19:48:06
 * @LastEditTime: 2020-10-23 09:49:42
 * @LastEditors: hanfengmi
 * @Description: 
 */
class Compiler {
    constructor(vm){
        this.el = vm.$el;
        this.method = vm.$method;
        this.vm = vm
        this.compile(this.el)
    }
    // 编译模板，处理文本节点和元素节点
    compile (el){
        let childNodes = el.childNodes
        Array.from(childNodes).forEach(node => {
            if(this.isTextNode(node)){
                this.compilerText(node)
            }else if(this.isElementNode(node)){
                this.compilerElement(node)
            }

            if(node.childNodes && node.childNodes.length){
                this.compile(node)
            }
        })
    }
    // 编译元素节点，处理指令
    compilerElement(node) {
        Array.from(node.attributes).forEach(attr => {
            let attrName = attr.name
            if(this.isDirective(attrName)){
                attrName = attr.name.substr(2)
                let key = attr.value
                this.update(node, key, attrName)
            }
        })
    }

    update(node, key, attrName) {
        let uodateFn = null;
        if(attrName.indexOf(':')<0){
            uodateFn = this[attrName+'Updater']
            uodateFn && uodateFn.call(this, node, this.vm[key], key)
        }else {
            uodateFn = this[attrName.split(':')[0]+'Updater']
            uodateFn && uodateFn.call(this, node, key, attrName.split(':')[1])
        }
    }
    textUpdater(node, value, key){
        node.textContent = value
        // watcher
        new Watcher(this.vm, key, (newValue)=>{
            node.textContent = newValue
        })
    }
    modelUpdater(node, value, key){
        node.value = value
        // watcher
        new Watcher(this.vm, key, (newValue)=>{
            node.value = newValue
        })

        // 双向绑定
        node.addEventListener('input',()=>{
            this.vm[key] = node.value
        })
    }
    htmlUpdater(node, value, key){// 渲染html
        node.innerHTML = value
        // watcher
        new Watcher(this.vm, key, (newValue)=>{
            node.textContent = newValue
        })
    }
    onUpdater(node, key, comName){
        node.addEventListener(comName,this.method[key].bind(this.vm))
        // new Watcher(this.vm, key, (newValue)=>{
        //     node.textContent = newValue
        // })
    }
    // 编译文本节点，处理差值表达式
    compilerText(node) {
        let reg = /\{\{(.+?)\}\}/
        let value = node.textContent
        if(reg.test(value)){
            let key = RegExp.$1.trim();
            node.textContent = value.replace(reg, this.vm[key])

            // watcher
            new Watcher(this.vm, key, (newValue)=>{
                node.textContent = newValue
            })
        }

    }
    // 判断元素是否是指令
    isDirective(attrName){
        return attrName.startsWith('v-')
    }
    // 判断界定啊是否是文本节点
    isTextNode(node){
        return node.nodeType === 3
    }
    // 判断是否是元素节点
    isElementNode(node){
        return node.nodeType === 1
    }

}